﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MQ.Core.Util
{
    public static class ObjectExtension
    {
        /// <summary>
        /// object to json string
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToJson(this object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        /// <summary>
        /// json string to object<typeparamref name="T"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T ToObject<T>(this string value)
        {
            return JsonConvert.DeserializeObject<T>(value);
        }
        public static object ToObject(this string value)
        {
            return JsonConvert.DeserializeObject(value);
        }
        public static object ToObject(this string value,Type type)
        {
            DataContractJsonSerializer s = new DataContractJsonSerializer(type);
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(value));
            var obj = s.ReadObject(ms);
            ms.Dispose();

            return obj;
        }
        public static Newtonsoft.Json.Linq.JObject ToJObject(this string value)
        {
            if (value.IsEmpty()) value = "{}";
            return Newtonsoft.Json.Linq.JObject.Parse(value);
        }
        /// <summary>
        /// object to int32
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int ToInt32(this object value)
        {
            return Convert.ToInt32(value);
        }
        /// <summary>
        /// object to int64
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long ToInt64(this object value)
        {
            return Convert.ToInt64(value);
        }
        /// <summary>
        /// object is null
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsEmpty(this object value)
        {
            if (value != null && !string.IsNullOrEmpty(value.ToString()))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// string is null or empty
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrEmpty(value);
        }
        /// <summary>
        /// convert object list to string by separator
        /// </summary>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string Join(this object[] list,string separator)
        {
            return string.Join(separator, list);
        }
        /// <summary>
        /// convert list<T> to string by separator.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string Join<T>(this IEnumerable<T> list,string separator)
        {
            return string.Join(separator, list);
        }
        /// <summary>
        /// DataTable to List<typeparamref name="T"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static IList<T> DataTableToList<T>(this DataTable dt) where T:new()
        {
            // 定义集合    
            IList<T> ts = new List<T>();
            string tempName = "";

            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                // 获得此模型的公共属性      
                PropertyInfo[] propertys = t.GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    tempName = pi.Name;  // 检查DataTable是否包含此列    

                    if (dt.Columns.Contains(tempName))
                    {
                        // 判断此属性是否有Setter      
                        if (!pi.CanWrite) continue;

                        object value = dr[tempName];
                        if (value != DBNull.Value)
                            pi.SetValue(t, value, null);
                    }
                }
                ts.Add(t);
            }
            return ts;
        }
        /// <summary>
        /// list t to datatable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ListToDataTable<T>(this IEnumerable<T> list)
        {
            var props = typeof(T).GetProperties();
            var dt = new DataTable();
            dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
            if (list.Count() > 0)
            {
                for (int i = 0; i < list.Count(); i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in props)
                    {
                        object obj = pi.GetValue(list.ElementAt(i), null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    dt.LoadDataRow(array, true);
                }
            }
            return dt;
        }
        /// <summary>
        /// base64 to byte[]
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ToBytes(this string base64)
        {
            return Convert.FromBase64String(base64);
        }
        /// <summary>
        /// object to byte[]
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte[] ToBytes(this object obj)
        {
            byte[] buff;
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter iFormatter = new BinaryFormatter();
                iFormatter.Serialize(ms, obj);
                buff = ms.GetBuffer();
            }
            return buff;
        }
        public static object ToObject(this byte[] buff)
        {
            object obj;
            using (MemoryStream ms = new MemoryStream(buff))
            {
                IFormatter iFormatter = new BinaryFormatter();
                obj = iFormatter.Deserialize(ms);
            }
            return obj;
        }
        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetExtension(this string value)
        {
            
            return Path.GetExtension(value);
        }
        /// <summary>
        /// dictionary to object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static T ToObject<T>(this Dictionary<string,string> dic) where T:class,new()
        {
            var props = typeof(T).GetProperties();
            T t = new T();
            if (dic.Count > 0)
            {
                foreach(PropertyInfo pi in props)
                {
                    if (!pi.CanWrite) continue;
                    if (dic.ContainsKey(pi.Name))
                    {
                        object value = dic[pi.Name];
                        if (value != DBNull.Value)
                            pi.SetValue(t, value, null);
                    }
                    pi.SetValue(pi.Name, dic[pi.Name]);
                }
            }
            return t;
        }
        /// <summary>
        /// Task任务是否正常完成
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        public static bool Completed(this Task task)
        {
            if (task.Status == TaskStatus.RanToCompletion)
                return true;
            return false;
        }
    }
}
